/* eslint-disable @typescript-eslint/indent */
import { SetupContext, defineComponent, ref, watch } from 'vue';
import { dynamicViewProps, DynamicViewProps } from './dynamic-view.props';
import { componentMap, componentPropsConverter, loadRegister } from './components/maps';

const FDynamicView = defineComponent({
    name: 'FDynamicView',
    props: dynamicViewProps,
    emits: ['update:modelValue'],
    setup(props: DynamicViewProps, context: SetupContext) {
        const modelValue = ref(props.modelValue);
        loadRegister();

        function renderContent(contents: any[]) {
            return contents.map((contentSchema: any) => {
                return <FDynamicView v-model={contentSchema}></FDynamicView>;
            });
        }

        function render(viewSchema: any) {
            const componentKey = viewSchema.type;
            if (componentKey === 'ContentContainer') {
                return <div class={viewSchema.appearance.class}>{renderContent(viewSchema.contents)}</div>;
            }
            const Component = componentMap[componentKey];

            const propsConverter = componentPropsConverter[componentKey];
            const viewProps = propsConverter ? propsConverter(viewSchema) : {};

            const hasContent = viewSchema.contents && !!viewSchema.contents.length;
            const contentMap = hasContent
                ? (viewSchema.contents as Record<string, any>[]).reduce((mapResult: Record<string, any>, content: Record<string, any>) => {
                      const slot = content.slot || 'default';
                      mapResult[slot] = [...(mapResult[slot] || []), content];
                      return mapResult;
                  }, {})
                : {};
            const contentsRender = Object.keys(contentMap).reduce((render: Record<string, any>, slot: string) => {
                render[slot] = () => renderContent(contentMap[slot]);
                return render;
            }, {});
            return hasContent && Component ? (
                <Component {...viewProps}>{contentsRender}</Component>
            ) : Component ? (
                <Component {...viewProps}></Component>
            ) : (
                <div></div>
            );
        }

        watch(
            () => props.modelValue,
            (value: any) => {
                modelValue.value = value;
                return render(modelValue.value);
            }
        );

        return () => {
            return render(modelValue.value);
        };
    }
});
export default FDynamicView;
